home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / cnews.orig.lzh / relay / hdrmunge.c < prev    next >
C/C++ Source or Header  |  1989-06-27  |  8KB  |  278 lines

  1. /*
  2.  * Usenet header modification & generation
  3.  *
  4.  * Ideally, headers should never be modified; message text, including
  5.  * headers, should be passed untouched.  Path: and Xref: demand that this
  6.  * rule be violated, and we delete huge obsolete headers to save space.
  7.  *
  8.  * Delete obsolete & large headers and Xref (can't be right),
  9.  * as headers are read.
  10.  * Recognise Newsgroups: and if more than one group, generate Xref: &
  11.  * leave holes for the article numbers - fileart will fill them in.
  12.  * (Make rn look in history instead?)
  13.  *
  14.  * Pile up headers into a static buffer until end of buffer (i.e. next
  15.  * line might not fit) [checked in hdrsave()], end of headers, end of
  16.  * file, or byte count is exhausted [checked in cparttofp].  Then write
  17.  * them to disk.  Prepend hostname! to Path: value, during output.
  18.  */
  19.  
  20. #include <stdio.h>
  21. #include <sys/types.h>
  22. #include "libc.h"
  23. #include "news.h"
  24. #include "fileart.h"
  25. #include "headers.h"
  26. #include "article.h"
  27. #include "hdrint.h"
  28. #include "msgs.h"
  29.  
  30. /*
  31.  * HDRMEMSIZ is the length of a header-stashing buffer, which is used
  32.  * only during article-header copying.
  33.  * HDRMEMSIZ can be too small if memory is tight & will only hurt performance.
  34.  * Derivation: 630 bytes is a large header (after discarding *-Version:, etc.).
  35.  */
  36. #ifndef HDRMEMSIZ
  37. #ifdef SMALLMEM
  38. #define HDRMEMSIZ 630
  39. #else
  40. #define HDRMEMSIZ 8192            /* # bytes for saving headers in core */
  41. #endif    /* SMALLMEM */
  42. #endif    /* HDRMEMSIZ */
  43.  
  44. /* private */
  45. static char **hptrs = NULL;    /* saved-headers-ptrs array; allocated once */
  46.  
  47. /* forwards */
  48. FORWARD void emithdr(), hdrsave();
  49.  
  50. /*
  51.  * Generate an Xref: header from art->a_files.
  52.  * Turn slashes in art->a_files into colons in Xref:.
  53.  */
  54. void
  55. emitxref(art)
  56. register struct article *art;
  57. {
  58.     register char *slashp, *xrefs;
  59.  
  60.     if (!art->a_xref) {
  61.         art->a_xref = YES;
  62.         xrefs = strsave(art->a_files);
  63.         for (slashp = xrefs; (slashp = index(slashp, FNDELIM)) != NULL; )
  64.             *slashp++ = ':';
  65.         if (fprintf(art->a_artf, "%s %s %s\n",
  66.             xrefhdr.hdrnm, hostname(), xrefs) == EOF)
  67.             fulldisk(art, spoolnm(art));
  68.         free(xrefs);
  69.     }
  70. }
  71.  
  72. /*
  73.  * --- header copying starts here ---
  74.  */
  75.  
  76. /*
  77.  * Copy headers and delete or modify a few.  Assumes hdrparse has been called.
  78.  * Delete obsolete & large headers and Xref.
  79.  * Pile up other headers for later output (Path: is changed during output).
  80.  *
  81.  * art->a_artf may be NULL, and may get set by hdrsave.
  82.  */
  83. STATIC void
  84. hdrmunge(art, buffer, hdrlen, hdrlst)
  85. register struct article *art;
  86. register char *buffer;
  87. int hdrlen;            /* optimisation only */
  88. hdrlist hdrlst;            /* headers of negative utility: snuff 'em */
  89. {
  90.     register struct hdrdef **vhp;
  91.  
  92.     if (headdebug)
  93.         (void) fputs(buffer, stderr);
  94.     for (vhp = hdrlst; *vhp != NULL; vhp++)
  95.         if (STREQN(buffer, (*vhp)->hdrnm, (int)(*vhp)->hdrlen))
  96.             return;            /* don't save this header */
  97.     hdrsave(art, buffer, hdrlen);
  98. }
  99.  
  100. /*
  101.  * If headers already dumped, just write to art->a_artf.
  102.  * Else if there is room, stash "hdr" away until end of headers is seen
  103.  * (could just wait until Newsgroups: and Control: are seen, if seen)
  104.  * or there is no room left in the header buffer, then open the first
  105.  * article link (on art->a_artf) and dump the saved headers and the current
  106.  * header to it.
  107.  *
  108.  * Copy into art->a_haccum (in future, could read in directly,
  109.  * iff copying is high on the profile).
  110.  *
  111.  * hdrstore is static because it is used repeatedly, it only makes sense
  112.  * to have one active at a time, and there is no memory saving in allocating
  113.  * and deallocating it, particularly since copyart's (header) buffer must
  114.  * coexist with hdrstore.
  115.  */
  116. STATIC void
  117. hdrsave(art, hdr, hdrlen)
  118. register struct article *art;
  119. char *hdr;
  120. register int hdrlen;            /* optimisation only */
  121. {
  122.     if (art->a_artf != NULL) {
  123.         emithdr(art, hdr, hdrlen);
  124.         return;
  125.     }
  126.     if (art->a_haccum == NULL) {
  127.         static char hdrstore[HDRMEMSIZ];
  128.  
  129.         art->a_haccum = hdrstore;
  130.         art->a_haccum[0] = '\0';
  131.         art->a_hnext = art->a_haccum;
  132.         art->a_hbytesleft = HDRMEMSIZ;
  133.     }
  134.     if (art->a_hbytesleft > hdrlen) {
  135.         /* add new ptr.-to-this-header to tail of saved-hdr-ptr.-list */
  136.         if (art->a_hptrs == NULL) {
  137.             art->a_hpused = 0;
  138.             art->a_hpalloced = MINSHPTRS;
  139.             if (hptrs == NULL)    /* once only */
  140.                 hptrs = (char **) nemalloc((unsigned)
  141.                     (art->a_hpalloced * sizeof(char *)));
  142.             art->a_hptrs = hptrs;
  143.         }
  144.         while (art->a_hpused >= art->a_hpalloced) {
  145.             art->a_hpalloced += MINSHPTRS;
  146.             art->a_hptrs = hptrs = (char **)
  147.                 realloc((char *)art->a_hptrs, (unsigned)
  148.                 (art->a_hpalloced * sizeof(char *)));
  149.             if (art->a_hptrs == NULL)
  150.                 errunlock("out of memory (for art->a_hptrs)", "");
  151.         }
  152.         art->a_hptrs[art->a_hpused++] = art->a_hnext;
  153.  
  154.         /* (void) strcat(art->a_haccum, hdr); */
  155.         (void) strcpy(art->a_hnext, hdr);
  156.         art->a_hnext += hdrlen;        /* points at NUL byte */
  157.         art->a_hbytesleft -= hdrlen;
  158.     } else {
  159.         hdrdump(art, NOTALLHDRS);    /* don't file */
  160.         if (art->a_artf != NULL)
  161.             emithdr(art, hdr, hdrlen);
  162.     }
  163. }
  164.  
  165. /*
  166.  * Change Path: while writing it out, just dump other headers (hdr) verbatim.
  167.  */
  168. STATIC void
  169. emithdr(art, hdr, hdrlen)
  170. register struct article *art;
  171. char *hdr;
  172. register int hdrlen;
  173. {
  174.     if (STREQN(hdr, pathhdr.hdrnm, (int)pathhdr.hdrlen)) {
  175.         register char *oldpath, *hostnm = hostname();
  176.  
  177.         oldpath = skipsp(&hdr[pathhdr.hdrlen]);
  178.         /*
  179.          * V7 f?printf return 0 or EOF, not a byte count, so it is
  180.          * not portable to use fprintf's return value as a byte count.
  181.          */
  182.         if (fprintf(art->a_artf, "%s %s!", pathhdr.hdrnm, hostnm) ==
  183.             EOF || fputs(oldpath, art->a_artf) == EOF)
  184.             fulldisk(art, spoolnm(art));
  185.         else {
  186.             static unsigned hostlen = 0;
  187.  
  188.             if (hostlen == 0)
  189.                 hostlen = strlen(hostnm);
  190.             art->a_charswritten += pathhdr.hdrlen + STRLEN(" ") +
  191.                 hostlen + STRLEN("!") + strlen(oldpath);
  192.         }
  193.     } else {
  194.         if (fwrite(hdr, hdrlen, 1, art->a_artf) != 1)
  195.             fulldisk(art, spoolnm(art));
  196.         else
  197.             art->a_charswritten += hdrlen;
  198.     }
  199. }
  200.  
  201. /*
  202.  * Write out saved headers after opening on art->a_artf either a temporary
  203.  * file (using mktemp(3)) or the first article link, based on art->h.h_ngs &
  204.  * nxtartnum(); set a_tmpf to which ever name is opened.
  205.  * Modify Path: value on the way.
  206.  *
  207.  * If all headers were seen, then open the first link, link to the rest,
  208.  * and generate Xref:, else open a temporary name and write the article
  209.  * there (it will get filed later by hdrdump(...,ALLHDRS) or in insart()).
  210.  */
  211. void
  212. hdrdump(art, allhdrsseen)
  213. register struct article *art;
  214. boolean allhdrsseen;        /* all headers seen & hdrdeflt() called? */
  215. {
  216.     if (art->a_filed)
  217.         return;
  218.     if (allhdrsseen)
  219.         fileart(art);            /* set a_tmpf */
  220.     else if (art->a_artf == NULL) {
  221.         nnfree(&art->a_tmpf);
  222.         art->a_tmpf = strsave(SPOOLTMP);
  223.         (void) mktemp(art->a_tmpf);
  224.         art->a_unlink = YES;
  225.         art->a_artf = fopenwclex(art->a_tmpf, "w");
  226.         if (art->a_artf == NULL)
  227.             art->a_status |= ST_DROPPED;
  228.     }
  229.     if (art->a_artf != NULL &&
  230.         art->a_haccum != NULL && art->a_haccum[0] != '\0') {
  231.         register int i;
  232.         register char **pp;
  233.         register char *nxtln;
  234.         register int saved;
  235.  
  236.         for (i = 0, pp = art->a_hptrs; i < art->a_hpused; ++i, ++pp) {
  237.             if (i >= art->a_hpused-1)    /* last in-core hdr? */
  238.                 nxtln = art->a_hnext;
  239.             else
  240.                 nxtln = pp[1];
  241.             saved = *nxtln;
  242.             *nxtln = '\0';
  243.             emithdr(art, *pp, nxtln - *pp);
  244.                  *nxtln = saved;            /* restore */
  245.         }
  246.         /* art->a_haccum could be freed and zeroed here, if malloced */
  247.         art->a_haccum[0] = '\0';    /* paranoia */
  248.         art->a_hnext = art->a_haccum;    /* for next article */
  249.         art->a_hpused = 0;        /* trash saved-header-ptr-list */
  250.         /* reduce saved-header-ptr-list to original size */
  251.         if (art->a_hpalloced > MINSHPTRS) {
  252.             art->a_hpalloced = MINSHPTRS;
  253.             art->a_hptrs = hptrs = (char **)
  254.                 realloc((char *)art->a_hptrs, (unsigned)
  255.                 (art->a_hpalloced * sizeof(char *)));
  256.             if (hptrs == NULL)
  257.                 errunlock("can't free a_hptrs memory", "");
  258.         }
  259.     }
  260. }
  261.  
  262. /*
  263.  * hdrparse remembers this header if it's interesting.
  264.  * hdrmunge needs art->h.h_ngs to be set, so it is called second.
  265.  * hdrmunge saves or writes this header, unless it's deemed a waste of bytes.
  266.  * hdrmunge may call hdrdump(art, NOTALLHDRS).
  267.  * hdrdump counts art->a_charswritten.
  268.  */
  269. void
  270. hdrdigest(art, line, hdrlen)
  271. register struct article *art;
  272. register char *line;
  273. int hdrlen;
  274. {
  275.         hdrparse(&art->h, line, parsehdrs);
  276.     hdrmunge(art, line, hdrlen, hdrvilest);
  277. }
  278.